/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.bs.extensoesSwing;

import java.io.Serializable;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;

/**
 *
 * @author Bone
 */
public class DocumentFilter extends javax.swing.text.DocumentFilter implements Serializable {

    public static final String REGRA_DATA = "[^0-9|^/]";
    public static final String REGRA_CARACTER = "[^A-Z|^0-9|^,|^.|^ |^-|^,|^/|^:|^;|^!|^@|^-]";
    public static final String REGRA_EMAIL = "[^A-Z|^0-9|^,|^.|^ |^@]";
    public static final String REGRA_INTEIRO = "[^0-9]";
    public static final String REGRA_MONETARIO = "[^0-9|^R|^$|^.|^ |^-]";
    public static final String REGRA_REAL = "[^0-9|^.]";
    public static final String REGRA_PORCENTAGEM = "[^0-9|^.]";
    public static final String REGRA_HORA = "[^0-9|^:]";
    private String regra = REGRA_CARACTER;
    private int limiteDeCaracteres = 100;
    private Boolean limitarCaracteres = false;
    private OpcoesDeRegraDeValidacao opcoesDeRegraDeValidacao;
    private int casasDecimais = 2;
    private String mascara = "";
    private Boolean formatarString = true;

    public DocumentFilter() {
        setRegraDeValidacaoSelecionada(OpcoesDeRegraDeValidacao.CARACTER);
    }

    public DocumentFilter(OpcoesDeRegraDeValidacao regraValidacao) {
        setRegraDeValidacaoSelecionada(regraValidacao);
    }

    public String getRegraValidacao() {
        if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.CARACTER) {
            return REGRA_CARACTER;
        }
        if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.DATA) {
            return REGRA_DATA;
        }
        if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.INTEIRO) {
            return REGRA_INTEIRO;
        }
        if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.MONETARIO) {
            return REGRA_MONETARIO;
        }
        if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.REAL) {
            return REGRA_REAL;
        }
        if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.HORA) {
            return REGRA_HORA;
        }
        if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.E_MAIL) {
            return REGRA_EMAIL;
        }
        if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.PORCENTAGEM) {
            return REGRA_PORCENTAGEM;
        }
        return REGRA_CARACTER;
    }

    public OpcoesDeRegraDeValidacao getRegraDeValidacaoSelecionada() {
        return opcoesDeRegraDeValidacao;
    }

    public void setRegraDeValidacaoSelecionada(OpcoesDeRegraDeValidacao regraDeValidacaoSelecionada) {
        this.opcoesDeRegraDeValidacao = regraDeValidacaoSelecionada;
        regra = getRegraValidacao();
        if (regraDeValidacaoSelecionada == opcoesDeRegraDeValidacao.DATA) {
            setMascara("##/##/####");
        }
    }

    private Boolean aceitarCaracteres(String text) {
        if (limitarCaracteres) {
            if (limiteDeCaracteres < text.length()) {
                return false;
            }
        }
        if (getRegraDeValidacaoSelecionada() == OpcoesDeRegraDeValidacao.PORCENTAGEM) {
            if (text.length() > 5) {
                return false;
            }
        }

        return true;
    }

    public enum OpcoesDeRegraDeValidacao {

        DATA, CARACTER, INTEIRO, MONETARIO, REAL, HORA, E_MAIL, PORCENTAGEM
    }

    @Override
    public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
        if (aceitarCaracteres(text)) {
            if (formatarString) {
                text = formatar(text);
            }
            super.replace(fb, offset, length, text.replaceAll(regra, ""), attrs);
        }
    }

    @Override
    public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
        if (!aceitarCaracteres(string)) {
            if (formatarString) {
                string = formatar(string);
            }
            super.insertString(fb, offset, string.replaceAll(regra, ""), attr);
        }
    }

    public String formatar(String s) {
        if (s == null) {
            return "";
        }

        if (opcoesDeRegraDeValidacao == DocumentFilter.OpcoesDeRegraDeValidacao.MONETARIO) {
            s = formataMonetario(s);
        }
        if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.REAL) {
            s = ajustaCasasDecimais(s);
        }

        if (opcoesDeRegraDeValidacao == DocumentFilter.OpcoesDeRegraDeValidacao.PORCENTAGEM) {
            if (!s.contains("%")) {
                s = s + "%";
            }
        }
        if (opcoesDeRegraDeValidacao == DocumentFilter.OpcoesDeRegraDeValidacao.DATA) {
            if (!mascara.equals("")) {
                s = s.replace("/", "");
                char[] chars = s.toCharArray();
                char[] mask = mascara.toCharArray();
                String ret = "";
                int cont = 0;

                for (char c : chars) {
                    if (mask[cont] == '#') {
                        ret += String.valueOf(c);
                    } else {
                        ret += String.valueOf(mask[cont]);
                        ret += String.valueOf(c);
                        cont++;
                    }
                    if (cont < mask.length - 1) {
                        cont++;
                    } else {
                        s = ret;

                    }
                }
                s = ret;
            }
        }
        return s.toUpperCase();
    }

    private String formataMonetario(String s) {
        if (s.equals("R$ ")) {
            return s;
        }
        if (s.equals("R$")) {
            return "";
        }
        s = s.replace("R$", "");
        s = s.replace(" ", "");
        s = ajustaCasasDecimais(s);
        s = "R$ " + s;
        return s;
    }

    public String validaConteudo(String conteudo) {
        if (conteudo.equals("")) {
            if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.MONETARIO) {
                if (conteudo.equals("R$") || conteudo.equals("R$ ")) {
                    conteudo = "R$ 0";
                }
            }
            if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.PORCENTAGEM) {
                conteudo = "00.00%";
            }
        }
        return conteudo;
    }

    public String ajustaCasasDecimais(String s) {

        if (opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.MONETARIO
                || opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.REAL
                || opcoesDeRegraDeValidacao == OpcoesDeRegraDeValidacao.PORCENTAGEM
                && casasDecimais > 0) {
            if (!s.equals("") ) {
                int cont = 0;
                if (formatarString) {
                    if (s.contains(".")) {

                        String sDecimal = s.substring(s.indexOf("."), s.length());
                        char[] chars = sDecimal.toCharArray();
                        // A lógica casasDecimais + 1 é porque o ponto é incluido na contagem.
                        if (sDecimal.length() < casasDecimais + 1) {
                            for (cont = 0; cont <= casasDecimais; cont++) {
                                if (cont >= chars.length) {
                                    s += 0;
                                }
                            }
                        } else if (sDecimal.length() > casasDecimais + 1) {
                            s = s.substring(0, s.indexOf(".") + casasDecimais + 1);
                        }
                    } else {
                        for (cont = 0; cont < casasDecimais; cont++) {
                            s += "0";
                        }
                    }
                }
                s = s.replace(".", "");
                s = s.replace("R$", "");
                s = s.replace(" ", "");
                s = s.replace("%", "");

                if (s.length() > casasDecimais) {
                    char[] caractere = s.toCharArray();
                    s = s.substring(0, s.length() - casasDecimais) + ".";
                    for (cont = caractere.length - casasDecimais; cont < caractere.length; cont++) {
                        s += String.valueOf(caractere[cont]);
                    }
                }
            }
        }
        return s;
    }

    public String getRegra() {
        return regra;
    }

    public void setRegra(String regra) {
        this.regra = regra;
    }

    public int getCasasDecimais() {
        return casasDecimais;
    }

    public String getMascara() {
        return mascara;
    }

    public void setMascara(String mascara) {
        this.mascara = mascara;
    }

    public void setCasasDecimais(int casasDecimais) {
        this.casasDecimais = casasDecimais;
    }

    public Boolean getFormatarString() {
        return formatarString;
    }

    public void setFormatarString(Boolean formatarString) {
        this.formatarString = formatarString;
    }

    public Boolean getLimitarCaracteres() {
        return limitarCaracteres;
    }

    public void setLimitarCaracteres(Boolean limitarCaracteres) {
        this.limitarCaracteres = limitarCaracteres;
    }

    public int getLimiteDeCaracteres() {
        return limiteDeCaracteres;
    }

    public void setLimiteDeCaracteres(int limiteDeCaracteres) {
        this.limiteDeCaracteres = limiteDeCaracteres;
    }
    
}
